#include "stdafx.h"

#include <opencv2/legacy/legacy.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"

#include "ImageStitcher.h"
#include "PatchFinder.h"
#include "RGBColour.h"
#include "ImageMethods.h"

using namespace cv;
using namespace std;

PatchFinder::PatchFinder(ResourceLibrary* rl, ImageStitcher* is)
{
	resources = rl;
	stitcher = is;
	im = new ImageMethods();
	roi;
	validPatches;
}

PatchFinder::~PatchFinder(void)
{
}

/*
*	Defines Region Of Interest (ROI)
*	Overloaded: square ROI
*/
void PatchFinder::defineROI(Point start, int width, int height)
{
	//roi.push_back();
	int startX = start.x;
	int startY = start.y;
	roi.push_back(cvPoint( startX, startY ));
	roi.push_back(cvPoint( startX+width, startY ));
	roi.push_back(cvPoint( startX+width, startY+height ));
	roi.push_back(cvPoint( startX, startY+height ));
}

/*
*	Overloaded: polygon ROI
*/
void PatchFinder::defineROI(vector<Point2f> points)
{
	roi = points;
}

/*
*	Finds valid patches i.e. patches ithin bounds of the image
*/
vector<int> PatchFinder::findValidPatches()
{
	vector<int> blah;
	//vector<vector<Point2f>> cornersList = stitcher->warped_corners;
	vector<vector<Point2f>> cornersList = resources->warpedCorners;

	int result;
	int validCount;

	for (int i=0; i<cornersList.size(); i++)
	{
		vector<Point2f> c = cornersList[i];
		validCount = 0;
		for (int j=0; j<roi.size(); j++)
		{
			result = pointInPoly(c,roi[j]);
			if (result == 0)
			{
				break;
			}
			if (result == 1)
			{
				validCount++;
			}
		}
		if (validCount == roi.size())
		{
			validPatches.push_back(i);
		}
	}
	return blah;
}

int PatchFinder::pointInPoly(vector<Point2f> c, Point2f p)
{
	int res = 0;
	int i;
	int j;
	for ( i = 0,  j = c.size()-1; i <c.size(); j = i++) 
	{
		Point2f point_i = c.at(i);
		float polyiX = point_i.x;
		float polyiY = point_i.y;
		Point2f point_j = c.at(j);
		float polyjX = point_j.x;
		float polyjY = point_j.y;
		cout<<point_i<< " ::point_i" <<endl;
		cout<<point_j<< " ::point_j" <<endl;
		cout<<p.x<< " ::px" <<endl;
		cout<<p.y<< " ::py" <<endl;
		cout<< ":::::::::::::::::::::" <<endl;
		if ( ((polyiY>p.y) != (polyjY>p.y)) && (p.x < (polyjX-polyiX) * (p.y-polyiY) / (polyjY-polyiY) + polyiX) )
		{
			res = !res;
		}
		cout<<res<<endl;
	}
	return res;
}

void PatchFinder::displayWarpedImages()
{
	namedWindow( "Warped ", CV_WINDOW_AUTOSIZE );
	for(int i=0;i<resources->warpedImages.size();i++)
	{
		cvShowImage("Warped", &resources->warpedImages.at(i));
		waitKey(0);
	}
}

void PatchFinder::displayWarpedImagesROI()
{
	namedWindow( "Warped ROI", CV_WINDOW_AUTOSIZE );
	for(int i=0;i<resources->warpedImages.size();i++)
	{
		Mat lines = &resources->warpedImages.at(i);
		line( lines, roi[0], roi[1],Scalar( 0, 0, 255), 4);
		line( lines, roi[1], roi[2],Scalar( 0, 0, 255), 4);
		line( lines, roi[2], roi[3],Scalar( 0, 0, 255), 4);
		line( lines, roi[3], roi[0],Scalar( 0, 0, 255), 4);
		//imshow("Lines",lines);
		cvShowImage("Warped ROI", &resources->warpedImages.at(i));
		waitKey(0);
	}
}

void PatchFinder::displayValidPatches()
{
	//namedWindow( "Warped ", CV_WINDOW_AUTOSIZE );
	Mat img1, img2;
	for(int i=0;i<validPatches.size();i++)
	{
		img1 = &resources->warpedImages.at(validPatches.at(i));
		img2 = img1(Rect(roi[0].x,roi[0].y, roi[1].x-roi[0].x, roi[3].y-roi[0].y));
		imshow("Patch",img2);
		resources->addPatches(img2);
		//cvShowImage("Warped", &resources->warpedImages.at(i));
		waitKey(0);
	}
}

void PatchFinder::savePatches()
{
	for(int i=0;i<resources->patches.size();i++)
	{
		std::stringstream sstm;
		sstm << "images/patches/patch" << i;
		String filename = sstm.str();
		im->saveImage(&resources->patches.at(i),filename);
	}
}




 